package net.miranti.dao;

import java.io.IOException;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.google.inject.Singleton;

public class ResourceLocalDaoUtils {
	private static EntityManagerFactory emf;
	private static final ThreadLocal<EntityManager> em = new ThreadLocal<EntityManager>();
	
	public static void start() {
		start("default");
	}

	public static void start(Map props) {
		start("default", props);
	}

	public static synchronized void start(String unit) {
		if (emf==null)
			emf = Persistence.createEntityManagerFactory(unit);
	}

	public static synchronized void start(String unit, Map props) {
		if (emf==null)
			emf = Persistence.createEntityManagerFactory(unit, props);
	}

	public static synchronized void stop() {
		if (emf.isOpen())
			emf.close();
	}

	public static EntityManager getEntityManager() {
		if (em.get()==null)
			em.set(emf.createEntityManager());
		return em.get();
	}
	
	public static void beginTransaction() {
		getEntityManager().getTransaction().begin();
	}
	public static void markTransactionForRollback() {
		EntityManager manager = em.get();
		if (manager!=null) {
			EntityTransaction tx = manager.getTransaction();
			if (tx.isActive())
				tx.setRollbackOnly();
		}
	}
	public static void releaseTransaction() {
		EntityManager manager = em.get();
		if (manager!=null) {
			EntityTransaction tx = manager.getTransaction();
			if (tx.isActive()) {
				if (tx.getRollbackOnly())
					tx.rollback();
				else tx.commit();
			}
			manager.close();
			em.remove();
		}
	}
	
	@Singleton
	public static class OpenPersistenceManagerInViewFilter implements Filter {
		public void init(FilterConfig arg0) {	}

		public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
		throws IOException, ServletException {
			try {
				chain.doFilter(req, res);
			} finally {
				releaseTransaction();
			}
		}
		public void destroy() {		}
	}
}